#include <sstream>
#include <cmath>
#include "plural.h"

//赋值符重载
jieningPlural& jieningPlural::operator =(const jieningPlural& obj)
{
	if(this == &obj)
	{
		return *this;
	}

	this->m_real = obj.m_real;
	this->m_imag = obj.m_imag;

	return *this;
}

//加号重载
jieningPlural jieningPlural::operator +(const jieningPlural& obj)
{
	return jieningPlural((this->m_real+obj.m_real), (this->m_imag+obj.m_imag));
}
jieningPlural jieningPlural::operator +(double val)
{
	return jieningPlural((this->m_real+val), this->m_imag);
}
jieningPlural& jieningPlural::operator +=(const jieningPlural& obj)
{
	this->m_real += obj.m_real;
	this->m_imag += obj.m_imag;
	return *this;
}
jieningPlural& jieningPlural::operator +=(double val)
{
	this->m_real += val;
	return *this;
}

//减号重载
jieningPlural jieningPlural::operator -(const jieningPlural& obj)
{
	return jieningPlural((this->m_real-obj.m_real), (this->m_imag-obj.m_imag));
}
jieningPlural jieningPlural::operator -(double val)
{
	return jieningPlural((this->m_real-val), this->m_imag);
}
jieningPlural& jieningPlural::operator -=(const jieningPlural& obj)
{
	this->m_real -= obj.m_real;
	this->m_imag -= obj.m_imag;
	return *this;
}
jieningPlural& jieningPlural::operator -=(double val)
{
	this->m_real -= val;
	return *this;
}

//乘号重载
jieningPlural jieningPlural::operator *(const jieningPlural& obj)
{
	return jieningPlural((this->m_real * obj.m_real - this->m_imag *  obj.m_imag), (this->m_real * obj.m_imag + this->m_imag * obj.m_real));
}
jieningPlural jieningPlural::operator *(double val)
{
	return jieningPlural((this->m_real * val), (this->m_imag * val));
}
jieningPlural& jieningPlural::operator *=(const jieningPlural& obj)
{
	double tmp = this->m_real * obj.m_real - this->m_imag *  obj.m_imag;
	this->m_real = tmp;	
	tmp = this->m_real * obj.m_imag + this->m_imag * obj.m_real;
	this->m_imag = tmp;
	return *this;
}
jieningPlural& jieningPlural::operator *=(double val)
{
	this->m_real *= val;
	this->m_imag *= val;
	return *this;
}

// 除号重载
// (ac+bd)/(c^2+d^2) + i(bc-ad)/(c^2+d^2)
jieningPlural jieningPlural::operator /(const jieningPlural& obj)
{
	double objmod = obj.getModulus();
	if(objmod < jieningPlural::ZEROVAL)
	{
		return *this;
	}
	objmod *= objmod;

	double tmpr = this->m_real * obj.m_real + this->m_imag * obj.m_imag;
	tmpr /= objmod;
	
	double tmpi = this->m_imag * obj.m_real - this->m_real * obj.m_imag;
	tmpi /= objmod;

	return jieningPlural(tmpr, tmpi);
}

jieningPlural jieningPlural::operator /(double val)
{
	if(abs(val) < jieningPlural::ZEROVAL)
	{
		return *this;
	}

	return jieningPlural(this->m_real/val, this->m_imag/val);
}

jieningPlural& jieningPlural::operator /=(const jieningPlural& obj)
{
	double objmod = obj.getModulus();
	if(objmod < jieningPlural::ZEROVAL)
	{
		return *this;
	}
	objmod *= objmod;

	double tmpr = this->m_real * obj.m_real + this->m_imag * obj.m_imag;
	tmpr /= objmod;
	
	double tmpi = this->m_imag * obj.m_real - this->m_real * obj.m_imag;
	tmpi /= objmod;

	this->m_real = tmpr;
	this->m_imag = tmpi;

	return *this;
}

jieningPlural& jieningPlural::operator /=(double val)
{
	if(abs(val) < jieningPlural::ZEROVAL)
	{
		return *this;
	}
	this->m_real /= val;
	this->m_imag /= val;
	return *this;
}

bool jieningPlural::operator ==(const jieningPlural& obj) const
{
	if(abs(this->m_real - obj.m_real) < jieningPlural::ZEROVAL && 
		abs(this->m_imag - obj.m_imag) < jieningPlural::ZEROVAL)
	{
		return true;
	}
	return false;
}

bool jieningPlural::operator <(const jieningPlural& obj) const
{
	if(abs(this->getModulus() - obj.getModulus()) < jieningPlural::ZEROVAL)
	{
		if(abs(this->getArg() - obj.getArg()) <	jieningPlural::ZEROVAL)
		{
			return false;
		}	
		return this->getArg() < obj.getArg();
	}
	return this->getModulus() < obj.getModulus();
}

bool jieningPlural::operator <=(const jieningPlural& obj) const
{
	return ((*this) == obj) ? true : ((*this) < obj);
}
bool jieningPlural::operator >(const jieningPlural& obj) const
{
	if(abs(this->getModulus() - obj.getModulus()) < jieningPlural::ZEROVAL)
	{
		if(abs(this->getArg() - obj.getArg()) <	jieningPlural::ZEROVAL)
		{
			return false;
		}	
		return this->getArg() > obj.getArg();
	}
	return this->getModulus() > obj.getModulus();
}

bool jieningPlural::operator >=(const jieningPlural& obj) const
{
	return ((*this) == obj) ? true : ((*this) > obj);
}

//取得复数模
double jieningPlural::getModulus() const
{
	return sqrt(this->m_real * this->m_real + this->m_imag * this->m_imag);
}

//复数幅角(弧度)
double jieningPlural::getArg() const
{
	double themod = this->getModulus();
	if(themod < jieningPlural::ZEROVAL)
	{
		return 0;
	}
	double thearg = acos(this->m_real / themod);
	if(this->m_imag < 0.0)
	{
		thearg = 2.0*jieningPlural::PI - thearg;
	}
	return thearg;
}

string jieningPlural::toString() const
{ 
	ostringstream strbuf;
	strbuf<<"("<<this->m_real<<", "<<this->m_imag<<"i)";
	return string(strbuf.str());
}
string jieningPlural::toStringMGd() const
{
	ostringstream strbuf;
	strbuf<<"("<<this->getModulus()<<"M, "<<(this->getArg()*180.0/jieningPlural::PI)<<"Ad)";
	return string(strbuf.str());
}
string jieningPlural::toStringMG() const
{
	ostringstream strbuf;
	strbuf<<"("<<this->getModulus()<<"M, "<<this->getArg()<<"Ar)";
	return string(strbuf.str());
}
std::ostream& operator<<(std::ostream& out, jieningPlural& thepl)
{
	out<<thepl.toString();
	return out;
}
std::ostream& operator<<(std::ostream& out, const jieningPlural& thepl)
{
	out<<thepl.toString();
	return out;
}
